/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.util;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.swing.event.EventListenerList;

/**
 * Simple PropertyMap for storing properties associated with a key.<br>
 * <b>NOTE</b>: Added PropertyChangeListener will not serialized!
 *
 */
public class SimplePropertyMap implements Serializable, Cloneable {
	private static final long serialVersionUID = -4700035950350086427L;
	
	private Map<String, Object> map;
	private transient EventListenerList propertyChangeListener;
	
	public SimplePropertyMap() {
		map = new LinkedHashMap<String, Object>();
	}
	
	public SimplePropertyMap(Map<String, Object> map) {
		this.map = new LinkedHashMap<String, Object>(map);
	}
	
	public SimplePropertyMap(SimplePropertyMap spm) {
		this(spm.map);
	}
	
	protected EventListenerList getPropertyChangeListenerList() {
		if(propertyChangeListener == null) {
			propertyChangeListener = new EventListenerList();
		}
		
		return propertyChangeListener;
	}
	
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		getPropertyChangeListenerList().add(PropertyChangeListener.class, 
				listener);
	}
	
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		getPropertyChangeListenerList().remove(PropertyChangeListener.class, 
				listener);
	}
	
	protected PropertyChangeListener[] getPropertyChangeListeners() {
		return getPropertyChangeListenerList().getListeners(
				PropertyChangeListener.class);
	}
	
	protected void firePropertyChangeListeners(String propertyName, 
			Object oldValue, Object newValue) {
		PropertyChangeEvent evt = new PropertyChangeEvent(this, 
				propertyName, 
				oldValue, 
				newValue);
		firePropertyChangeListeners(evt);
	}
	
	protected void firePropertyChangeListeners(PropertyChangeEvent pce) {
		for(PropertyChangeListener listener: getPropertyChangeListeners()) {
			listener.propertyChange(pce);
		}
	}
	
	public void putValue(String key, Object newValue) {
		Object oldValue = map.get(key);
		map.put(key, newValue);
		firePropertyChangeListeners(key, oldValue, newValue);
	}
	
	/**
	 * Returns the value to which the specified key is mapped, or null if 
	 * this map contains no mapping for the key. 
	 * @param key the key whose associated value is to be returned
	 * @return the value to which the specified key is mapped, 
	 * or <code>null</code> if this map contains no mapping for the key 
	 */
	public Object getValue(String key) {
		return map.get(key);
	}
	
	public Object[] getKeys() {
		return map.keySet().toArray();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof SimplePropertyMap) {
			SimplePropertyMap other = (SimplePropertyMap) obj;
			return other.map.equals(map);
		}
		
		return super.equals(obj);
	}
	
	@Override
	public Object clone() {
		return new SimplePropertyMap(map);
	}
}
